/*
 * PopulationAbstract.h
 *
 *  Created on: 12 juin 2011
 *      Author: dimo
 */

#ifndef POPULATIONABSTRACT_H_
#define POPULATIONABSTRACT_H_

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <exception>

#include "Individual.h"
#include "PopulationAbstract.h"

using namespace std;

class PopulationAbstract {

private:
	/** The individuals generated during execution of the EA, which are considered for further use. */
	vector<Individual> globalPopulation;

	/** The indices of the elements of the <code>globalPopulation</code> ArrayList
	 * which contain <code>null</code>. The indices of the individuals in the global population
	 * are static, which means that when the global population contains three individuals with the indices
	 * 1, 2 and 3 and the second individual is removed from the global population, the global population still contains
	 * three elements, but only the first and the third point to an individual, whereas the second is <code>null</code>.
	 * The <code>freeIdentities</code> list then contains of the single element <code>2</code>.
	 */
	vector<int> freeIdentities;

	/** The individuals which have been selected (by the selector) for variation. */
	vector<int> parents;

	/** The individuals generated by applying recombination and mutation to the parents (by the variator). */
	vector<int> offspring;

	/** The seed of the random generator. Two runs of the variator with the same seed generate the same result. */
	int seed;

	/** The current generation of the population. */
	int generation;

	/** The time interval in seconds in which the state file is checked in the state machine. */
	int pollingInterval;

	/** Says whether the debug messages should be printed (<code>true</code>) or whether the variator should execute silently (<code>false</code>). */
	bool debugPrint;

	// PISA configuration variables

	/** The size of the initial population. */
	int alpha;

	/** The number of parents chosen by the selector for variation. Has to be equal to alpha. */
	int mu;

	/** The number of offspring generated by variating the <code>mu</code> parents. Has to be equal to alpha. */
	int lambda;

	/** The number of objectives. */
	int dim;

	// Communication files

	/** Communication file containing the state of the state machine. The file contains one single integer value. */
	string stateFile;

	/** Communication file containing the indices of the individuals which are considered for further use by the selector. The parents are a subset of
	 * these individuals. Each line of the file contains one single integer number (the index). Additionally, the first line is the number of indices and the
	 * last line is an <code>END</code> tag. */
	string archiveFile;

	/** Communication file containing the indices of the offspring. The offspring is generated by the variator by applying recombination
	 * and mutation to the parents (which have been chosen by the selector). Each line of the file contains one integer number (the index)
	 * plus the objective space values of the corresponding individual. Additionally, the first line is the number of elements
	 * ((number of indices)*(number of objective space values + 1)) and the
	 * last line is an <code>END</code> tag. */
	string variatorFile;

	/** Communication file containing the parents which have been chosen for variation by the selector. The selector chooses them from its own archive of reusable individuals
	 * (the indices of which are stored in the archive file) and the offspring generated by the variator. Each line of the file contains one single integer number (the index). Additionally, the first line is the number of indices and the
	 * last line is an <code>END</code> tag. */
	string selectorFile;

	/** Communication file containing the the sizes of the initial population, of the parents and of the offspring as well as the number of objectives. */
	string configFile;

	/** Communication file containing the initial population generated by the variator. Each line of the file contains one integer number (the index)
	 * plus the objective space values of the corresponding individual. Additionally, the first line is the number of elements
	 * ((number of indices)*(number of objective space values + 1)) and the
	 * last line is an <code>END</code> tag. */
	string initialFile;

	// Other filenames

	/** The name of the file which contains the user-defined variator parameters which are read in State 0. */
	string paramFileName;

	/** The name of the file where the final population will be printed. After the last variation, the selector executes once more. All individuals
	 * which are contained in the archive file afterwards are written to the output file. For each individual, the index plus the objective space
	 * values are written.
	 */
	string outputFileName;

	// Filepaths

	/**
	 * Holds the path and name-parts of the communication files of the PISA protocol.
	 * For example if <code>commFilePath</code> is <code>./PISA_</code>,
	 * then the variator file will be appended a <code>var</code>: <code>./PISA_var</code>.
	 * The same goes for the status (<code>sta</code>), selector files (<code>sel</code>),
	 * initial files (<code>ini</code>), the archive files (<code>arc</code>) and the
	 * configuration files (<code>cfg</code>).
	 */
	string commFilePath;


	PopulationAbstract();

	// Abstract methods: These methods have to be implemented by the user in Population.java

	/** Initializes the population with <code>mu</code> individuals. */
	virtual void initialize() = 0;

	/** Performs variation on a set of given individuals.
	 *
	 * @param offspring the indices of the individuals which have to be variated
	 */
	virtual void performVariation(int offspring[]) = 0;

	/** Tests if the stopping criterion of the EA has been met.
	 *
	 * @return true if the EA should stop, false if it should continue with the next generation
	 */
	virtual bool isFinished() = 0;

	/** Sets the user-defined parameters. The parameter file can only contain parameters
	 * which are either handled in this method or in the <code>setFixedParam</code> method of
	 * the abstract population class <code>PopulationAbstract</code>.
	 *
	 * @param paramName the name of the parameter to be set
	 * @param paramValue the value of the parameter to be set
	 * @return true is the parameter has been successfully set, else false
	 */
	virtual bool setNonfixedParam(string paramName, string paramValue) = 0;

	/** Tests the parameter for consistent values. If there are some values or value combination
	 * that should not be allowed (e.g. mu != lambda), the user can test them in this method.
	 * If all values are allowed, the method can be left empty.
	 */
	virtual void testParam() = 0;

	/** Writes all individuals of the population to the output file. The name of the output file is specified in the parameter
	 * file.
	 */
	virtual void writeOutput() = 0;

	// "normal" methods
	void performClean();
	void writePopulation(string filename);
	void writePopulation(string filename, int identities[]);
	bool setFixedParam(string paramName, string paramValue);
	Individual getIndividual(int id);
	Individual copyIndividual(Individual ind);
	int addIndividual(Individual ind);
	void removeIndividual(int id);
	void evalIndividual(int id);

public:
	void variate();
	static bool contains(vector<int> vectorOfInts, int i);

};

#endif /* POPULATIONABSTRACT_H_ */
